package com.tea.room.service.wechat.impl;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.alibaba.fastjson.JSONObject;
import com.tea.room.timer.TimerTask;
import com.tea.room.util.MD5;

public class WeChatUtil {

    private static Logger logger = LoggerFactory.getLogger(TimerTask.class);

    /**
     * 获取用户的ip
     */
    public static String GetIp() {
        InetAddress ia = null;
        try {
            ia = InetAddress.getLocalHost();
            String localip = ia.getHostAddress();
            return localip;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取Access_token
     * 
     * @Title: getAccess_token
     */
    public static String getAccess_token(String url, String appid, String appsecret) {
        com.tea.room.util.HttpClient client = com.tea.room.util.HttpClient.getInstance();
        String params = url + "?grant_type=client_credential&appid=" + appid + "&secret=" + appsecret;
        logger.info("获取Access_token url:" + params);
        String result = client.sendHttpGet(params);
        return result;
    }

    /**
     * 获取支付所需签名
     */
    public static String getPayCustomSign(Map<String, Object> bizObj, String key) throws Exception {
        String bizString = FormatBizQueryParaMap(bizObj, false);
        return MD5.sign(bizString, key);
    }

    /**
     * 拼接参数
     */
    public static String FormatBizQueryParaMap(Map<String, Object> paraMap, boolean urlencode) throws Exception {
        String buff = "";
        try {
            List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(paraMap.entrySet());

            Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {
                public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            for (int i = 0; i < infoIds.size(); i++) {
                Map.Entry<String, Object> item = infoIds.get(i);
                if (item.getKey() != "") {
                    String key = item.getKey();
                    String val = item.getValue() + "";
                    if (urlencode) {
                        val = URLEncoder.encode(val, "utf-8");
                    }
                    buff += key + "=" + val + "&";
                }
            }
            if (buff.isEmpty() == false) {
                buff = buff.substring(0, buff.length() - 1);
            }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        return buff;
    }

    /**
     * Map转xml @Title: ArrayToXml @Description: TODO() @param: @param
     * arr @param: @return @return: String @throws
     */
    public static String ArrayToXml(Map<String, Object> arr) {
        String xml = "<xml>";
        Iterator<Entry<String, Object>> iter = arr.entrySet().iterator();
        while (iter.hasNext()) {
            Entry<String, Object> entry = iter.next();
            String key = entry.getKey();
            String val = entry.getValue() + "";
            if (IsNumeric(val)) {
                xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">";
            } else
                xml += "<" + key + ">" + val + "</" + key + ">";
        }
        xml += "</xml>";
        return xml;
    }

    /**
     * XML格式字符串转换为Map
     *
     * @param strXML
     *            XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, Object> xmlToMap(String strXML) {
        Map<String, Object> data = new HashMap<String, Object>();
        InputStream stream = null;
        try {
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            org.w3c.dom.Document doc = documentBuilder.parse(stream);
            doc.getDocumentElement().normalize();
            NodeList nodeList = doc.getDocumentElement().getChildNodes();
            for (int idx = 0; idx < nodeList.getLength(); ++idx) {
                Node node = nodeList.item(idx);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                    data.put(element.getNodeName(), element.getTextContent());
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (stream != null)
                    stream.close();
            } catch (Exception ex) {
                // do nothing
            }
        }
        return data;

    }

    public static boolean IsNumeric(String str) {
        if (str.matches("\\d *")) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 转换一个xml格式的字符串到json格式
     * 
     * @param xml
     *            xml格式的字符串
     * @return 成功返回json 格式的字符串;失败反回null
     */
    public static JSONObject xml2JSON(InputStream is) {
        JSONObject obj = new JSONObject();
        try {
            SAXReader sb = new SAXReader();
            Document doc = sb.read(is);
            Element root = doc.getRootElement();
            obj.put(root.getName(), iterateElement(root));
            return obj;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 一个迭代方法
     * 
     * @param element
     *            : org.jdom.Element
     * @return java.util.Map 实例
     */
    @SuppressWarnings("all")
    private static Map iterateElement(Element element) {
        List jiedian = element.elements();
        Element et = null;
        Map obj = new HashMap();
        List list = null;
        for (int i = 0; i < jiedian.size(); i++) {
            list = new LinkedList();
            et = (Element) jiedian.get(i);
            if (et.getTextTrim().equals("")) {
                if (et.elements().size() == 0)
                    continue;
                if (obj.containsKey(et.getName())) {
                    list = (List) obj.get(et.getName());
                }
                list.add(iterateElement(et));
                obj.put(et.getName(), list);
            } else {
                if (obj.containsKey(et.getName())) {
                    list = (List) obj.get(et.getName());
                }
                list.add(et.getTextTrim());
                obj.put(et.getName(), list);
            }
        }
        return obj;
    }
    
    /**
     * 请求微信
     */
    public static JSONObject sendWeChat(String xml, String url) {
        HttpClient httpClient = new HttpClient(new HttpClientParams(), new SimpleHttpConnectionManager(true));
        InputStream is = null;
        PostMethod method = null;
        JSONObject result = null;
        try {
            method = new PostMethod(url);
            method.setRequestBody(xml);
            httpClient.executeMethod(method);
            is = method.getResponseBodyAsStream();// 读取响应
            result = WeChatUtil.xml2JSON(is);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (method != null) {
                method.releaseConnection();
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return result;
    }
    
    /**
     * 封装页面支付参数
     * 
     * @param map
     * @return
     * @throws Exception
     */
    public static Map<String, Object> getH5PayParams(Map<String, Object> map, String key) throws Exception {
        Map<String, Object> signMap = new HashMap<String, Object>();
        signMap.put("appId", map.get("appid"));
        signMap.put("timeStamp", map.get("timestamp"));
        signMap.put("nonceStr", map.get("nonce_str"));
        signMap.put("package", "prepay_id=" + map.get("prepayid"));
        signMap.put("signType", "MD5");
        String paySign = WeChatUtil.getPayCustomSign(signMap, key);
        signMap.put("paySign", paySign);
        return signMap;
    }
    
    
}
